﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace Factory
{
    public partial class CadastroCheque : Form
    {
        public CadastroCheque()
        {
            InitializeComponent();
        }

        #region Propriedades
        bool validou = false;
        int codChequeRemocao = 0;
        int numCheque;
        string erro = string.Empty;
        double limiteClienteFactory;

        private IList<Cliente> lstCliente = new List<Cliente>();

        //cheques adicionados ao bordero
        private IList<Cheque> lstCheques = new List<Cheque>();

        //cheques rejeitados SpcSerasa
        private IList<Cheque> lstChequesRejeitadosSpcSerasa = new List<Cheque>();

        //cheques rejeitados por risco de numeros documento
        private IList<Cheque> lstChequesRejeitadosPorNumDoc = new List<Cheque>();

        //cheques rejeitados por risco de cpf
        private IList<Cheque> lstChequesRejeitadosPorCpf = new List<Cheque>();

        private IList<Banco> lstBancos = new List<Banco>();
        #endregion

        #region Métodos
        private void CadastroCheque_Load(object sender, EventArgs e)
        {
            CarregarClientes();
            CarregarBancos();
            txtDataSerasa.Text = DateTime.Now.ToString("dd/MM/yyyy");
        }

        private void CarregarBancos()
        {
            lstBancos = BancoDAO.obtemBancos();
            BindingSource bs = new BindingSource();

            lstBancos.Insert(0, (
                new Banco()
                {
                    id = "0",
                    nome = "Selecione um Banco",
                }
                            ));

            bs.DataSource = lstBancos;
            cboBanco.DataSource = bs.DataSource;

            cboBanco.DisplayMember = "nome";
            cboBanco.ValueMember = "id";
        }

        private void CarregarClientes()
        {
            try
            {
                ClienteDAO clienteDAO = new ClienteDAO();
                lstCliente = clienteDAO.ObterClientes();
                var lista = from c in lstCliente
                            select new
                            {
                                Id = c.id,
                                Nome = c.nome,
                                CPF = c.cpf,
                                Limite = c.limiteCredito.ToString("C"),
                                Limite_Atual = c.limiteAtual.ToString("C"),
                                Especial = c.especial,
                                Juridica = c.juridica,
                            };

                dataGridCliente.DataSource = lista.ToList();
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Erro!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnAdicionar_Click(object sender, EventArgs e)
        {
            bool podeAdicionar = VerificaCampos();

            if (podeAdicionar)
            {
                try
                {
                    validou = false;
                    string cpfCliente = txtCpfCliente.Text;
                    double valor = Convert.ToDouble(txtValor.Text);
                    DateTime dataComp = Convert.ToDateTime(txtComp.Text);
                    string cpfCheque = txtCpfCheque.Text;

                    Cheque c = new Cheque()
                    {
                        dataCompensacao = dataComp,
                        dataConsulta = DateTime.Today,
                        documentoEmissor = cpfCheque,
                        documentoCliente = cpfCliente,
                        IdBanco = Convert.ToInt32((String)cboBanco.SelectedValue),
                        valor = valor,
                        ResultadoConsulta = 1,
                        status = 0,
                        id = numCheque++,
                    };

                    bool valido = validarChequeSpcSerasa(c);

                    if (valido)
                    {
                        Cheque chequeCalculado = calcularPagamento(c);
                        lstCheques.Add(chequeCalculado);
                        CarregarCheques();   
                    }
                    if (!valido)
                    {
                        MessageBox.Show("Cheque consta na base do SPC/SERASA", "Problemas com o cheque!", MessageBoxButtons.OK);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString(), "Erro!", MessageBoxButtons.OK);
                }
            }

            else
            {
                MessageBox.Show(erro.ToString(), "Problemas com os campos!", MessageBoxButtons.OK);
            }
        }

        private bool VerificaCampos()
        {
            if (!txtCpfCheque.MaskFull
                    || txtValor.Text == string.Empty
                    || txtCpfCliente.Text == string.Empty
                    || txtComp.Text == string.Empty
                    || cboBanco.SelectedIndex <= 0 || !txtComp.MaskFull
                    || (Convert.ToDateTime(txtComp.Text)) < DateTime.Today)
            {
                StringBuilder sb = new StringBuilder();

                sb.Append("Os seguintes campos obrigatórios estão com problemas de preenchimento: \n\n");
                sb.Append(txtCpfCliente.Text == string.Empty ? "-CPF Cliente em branco \n" : string.Empty);
                sb.Append(txtCpfCheque.MaskFull == false ? "-CPF Cheque em branco \n" : string.Empty);
                sb.Append(txtValor.Text == string.Empty ? "-Valor em branco \n" : string.Empty);
                sb.Append(txtComp.MaskFull == false ? "-Data Compensação em branco \n" : string.Empty);

                if (txtComp.MaskFull)
                {
                    sb.Append(Convert.ToDateTime(txtComp.Text) < DateTime.Today ? "-Data Compensação com data menor que a atual\n" : string.Empty);
                }

                sb.Append(cboBanco.SelectedIndex <= 0 ? "-Banco não selecionado \n" : string.Empty);
                sb.Append(txtDataSerasa.MaskFull == false ? "-Data Consulta SPC/Serasa em branco \n" : string.Empty);

                erro = sb.ToString();

                return false;
            }

            else
                return true;
        }

        private Cheque calcularPagamento(Cheque c)
        {
            RegraDAO regraDAO = new RegraDAO();
            Regra regra = regraDAO.ObterRegras();

            //calculo de prazo
            DateTime dataInicial = DateTime.Today;

            DateTime dataCompensacao = c.dataCompensacao;

            bool feriado = false;

            //Verifica se data de Compensacao é feriado,sabado,domingo...e enquanto for vai andando nos dias...
            do
            {
                dataDAO dataDaoBanco = new dataDAO();
                dataFeriado dataRetorno = dataDaoBanco.obtemData(dataCompensacao);

                if (dataRetorno != null)
                {
                    feriado = true;
                    dataRetorno = null;
                    dataCompensacao = dataCompensacao.AddDays(1);
                }

                else
                {
                    feriado = false;
                }


            } while (feriado);

            TimeSpan date = dataCompensacao - dataInicial;

            int totalDias = date.Days;

            double valorPago = 0;
            double valorDescontado = 0;

            double taxa = 0;

            if (txtJuros.Text == string.Empty)
            {
                taxa = regra.TaxaCobradaPorCheque; //Esse valor deverá vir da tabela de regras
            }

            else
            {
                taxa = Convert.ToDouble(txtJuros.Text);
            }
            
            double valorCheque = c.valor;
            double prazo = totalDias;

            prazo = prazo / 30;
            taxa = taxa / 100;

            double calculoParentesis = Math.Pow(1 + taxa, prazo);
            valorDescontado = (valorCheque * (calculoParentesis - 1)) / calculoParentesis;
            valorPago = valorCheque - valorDescontado;

            //txtValorDescontado.Text = Convert.ToString(valorDescontado);
            c.valorPago = valorPago;
            c.dataCompensacao = dataCompensacao;

            return c;
        }

        private bool VerificaLimitePorCpf(Cheque c)
        {
            try
            {
                ChequeDAO chequeDAO = new ChequeDAO();

                //lista de cheques no banco de dados
                IList<Cheque> lstChequeRecebidosDoBanco = chequeDAO.ObterCheques();

                //busco as regras
                RegraDAO regraDAO = new RegraDAO();
                Regra regra = regraDAO.ObterRegras();

                int numeroDeChequesIguaisDoBanco = 0;
                int numeroDeChequesIguaisDoBordero = 0;

                //pego o cheque que estou adicionando e comparo com os existentes no banco para ver se existe algum com msm cpf      
                //caso o limite por cpf no banco já ultrapasse é avisado que o limite foi atingido                                   
                numeroDeChequesIguaisDoBanco = lstChequeRecebidosDoBanco.Where(ch => ch.documentoEmissor == c.documentoEmissor).Count();
                if (numeroDeChequesIguaisDoBanco > regra.LimitePorCpf)
                {
                    return false;
                }

                //caso o limite nao tenha sido atingido no banco, porém ao tentar adicionar o cheque em questao ele seja atingido é avisado.
                if (numeroDeChequesIguaisDoBanco + 1 > regra.LimitePorCpf)
                {
                    return false;
                }

                //pego o numero de cheques de msm cpf no meu bordero
                numeroDeChequesIguaisDoBordero = lstCheques.Where(o => o.documentoEmissor == c.documentoEmissor).Count();

                //somo com os do banco, pois devemos considerar o banco + bordero e caso o banco seja 0 tb efetuamos a comparacao por bordero
                int totalChequesIguais = numeroDeChequesIguaisDoBanco + numeroDeChequesIguaisDoBordero;

                if (totalChequesIguais > regra.LimitePorCpf)
                {
                    return false;
                }

                //caso o limite nao tenha sido atingido no banco e no bordero, porém ao tentar adicionar o cheque em questao ele seja atingido é avisado.
                if (totalChequesIguais + 1 > regra.LimitePorCpf)
                {
                    return false;
                }

                //passou por tudo
                return true;
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Erro!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        private void CarregarCheques()
        {
            try
            {
                var lista = from c in lstCheques
                            select new
                            {
                                Cod = c.id,
                                Documento = c.documentoEmissor,
                                Valor = c.valor.ToString("C"),
                                Data_Compensacao = c.dataCompensacao,
                                Valor_Pagamento = c.valorPago.ToString("C"),
                            };

                dataGridCheque.DataSource = lista.ToList();


                double total = 0;
                double troco = 0;

                foreach (Cheque ch in lstCheques)
                {
                    total = total + ch.valor;
                    troco = troco + ch.valorPago;
                }

                lblTotalDCheques.Text = total.ToString("C");
                lblTroco.Text = troco.ToString("C");

                if (total > limiteClienteFactory)
                {
                    lblLimit.ForeColor = System.Drawing.Color.Red;
                }

                else
                {
                    lblLimit.ForeColor = System.Drawing.Color.Black;
                }

            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Erro!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private bool validarChequeSpcSerasa(Cheque c)
        {
            SpcSerasaDAO spcSerasaDAO = new SpcSerasaDAO();
            IList<SpcSerasa> lstCpfsSpcSerasa = spcSerasaDAO.ObterCheques();

            foreach (SpcSerasa s in lstCpfsSpcSerasa)
            {
                if (c.documentoEmissor == s.cpf)
                {
                    return false;
                }
            }

            return true;
        }

        protected override bool ProcessCmdKey(ref Message message, Keys keys)
        {
            switch (keys)
            {
                case Keys.Escape:
                    //Process action here.
                    MenuPrincipal menu = new MenuPrincipal();
                    menu.Show();
                    this.Hide();
                    return false;
            }
            return false;
        }

        private void removerChequesNaoAprovadosPeloCpf()
        {
            foreach (Cheque c in lstChequesRejeitadosPorCpf)
            {
                lstCheques.Remove(c);
            }
        }

        private void removerChequesNaoAprovadosPorNumDocumento()
        {
            foreach (Cheque c in lstChequesRejeitadosPorNumDoc)
            {
                lstCheques.Remove(c);
            }
        }

        private void validaListaDeChequesPorCPF()
        {
            try
            {
                ChequeDAO chequeDAO = new ChequeDAO();
                FactoryDAO factoryDAO = new FactoryDAO();
                FactoryE factoryE = factoryDAO.obterDadosFactory();

                //Lista de cheques que constam no banco
                IList<Cheque> lstChequeRecebidos = chequeDAO.ObterCheques();

                //Obtendo regras
                RegraDAO regraDAO = new RegraDAO();
                Regra regra = regraDAO.ObterRegras();

                //pega porcentagem de emprestimo para realizar o calculo de quanto a factory pode emprestar
                double porcentagemEmprestimo = regra.PorcentagemEmprestimo;

                //Calcula quanto sera o valor que a factory podera emprestar
                double totalEmprestado = ((factoryE.valorAtual / 100) * porcentagemEmprestimo);

                foreach (Cheque c in lstCheques)
                {
                    double somaBanco = lstChequeRecebidos.Where(o => o.documentoEmissor == c.documentoEmissor).Sum(o => o.valor);
                    double somaBordero = lstCheques.Where(o => o.documentoEmissor == c.documentoEmissor).Sum(o => o.valor);

                    double resultado = ((somaBordero + somaBanco) / totalEmprestado) * 100;
                    if (resultado > regra.LimitePorCpf)
                    {
                        lstChequesRejeitadosPorCpf.Add(c);
                    }
                }
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Erro!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        //considera banco
        //private void validaListaDeChequesPorQtdDocumento()
        //{
        //    try
        //    {
        //        ChequeDAO chequeDAO = new ChequeDAO();

        //        RegraDAO regraDAO = new RegraDAO();
        //        Regra regra = regraDAO.ObterRegras();
                
        //        //Lista de cheques que constam no banco
        //        IList<Cheque> lstChequeRecebidos = chequeDAO.ObterCheques();

        //        foreach (Cheque c in lstCheques)
        //        {
        //            double somaBanco = lstChequeRecebidos.Where(o => o.documentoEmissor == c.documentoEmissor).Sum(o => o.valor);
        //            double somaBordero = lstCheques.Where(o => o.documentoEmissor == c.documentoEmissor).Sum(o => o.valor);

        //            double resultado = (c.valor / (somaBordero + somaBanco)) * 100;
        //            if (resultado > regra.LimitePorCheque)
        //            {
        //                lstChequesRejeitadosPorNumDoc.Add(c);
        //            }
        //        }                
        //    }

        //    catch (Exception ex)
        //    {
        //        MessageBox.Show(ex.ToString(), "Erro!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        //    }
        //}

        //nao considera banco
        private void validaListaDeChequesPorQtdDocumento()
        {
            try
            {
                ChequeDAO chequeDAO = new ChequeDAO();

                RegraDAO regraDAO = new RegraDAO();
                Regra regra = regraDAO.ObterRegras();

                //Lista de cheques que constam no banco
                IList<Cheque> lstChequeRecebidos = chequeDAO.ObterCheques();                

                foreach (Cheque c in lstCheques)
                {

                    double somaBordero = lstCheques.Where(o => o.documentoEmissor == c.documentoEmissor).Sum(o => o.valor);
                    double resultado = (c.valor / somaBordero) * 100;
                    if (resultado > regra.LimitePorCheque)
                    {
                        lstChequesRejeitadosPorNumDoc.Add(c);
                    }
                }
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Erro!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void removerChequesNaoAprovadosPeloSerasa()
        {
            foreach (Cheque c in lstChequesRejeitadosSpcSerasa)
            {
                lstCheques.Remove(c);
            }
        }

        private void validaListaDeCheques(IList<Cheque> lstChequesParaAvaliar)
        {
            SpcSerasaDAO spcSerasaDAO = new SpcSerasaDAO();
            IList<SpcSerasa> lstCpfsSpcSerasa = spcSerasaDAO.ObterCheques();

            lstChequesRejeitadosSpcSerasa = new List<Cheque>();

            foreach (SpcSerasa s in lstCpfsSpcSerasa)
            {
                foreach (Cheque c in lstChequesParaAvaliar)
                {
                    if (c.documentoEmissor == s.cpf)
                    {
                        lstChequesRejeitadosSpcSerasa.Add(c);
                    }
                }
            }
        }

        #endregion

        #region Eventos

        private void btnSubmeter_Click(object sender, EventArgs e)
        {
            if (validou != false)
            {
                try
                {
                    ChequeDAO chequeDAO = new ChequeDAO();              
                    double total = 0;
                    double troco = 0;

                    foreach (Cheque ch in lstCheques)
                    {
                        total = total + ch.valor;
                        troco = troco + ch.valorPago;
                    }

                    ClienteDAO clienteDAO = new ClienteDAO();
                    Cliente cli = clienteDAO.ObterClientesPorCpf(txtCpfCliente.Text);

                    if (cli.limiteAtual < total)
                    {
                        MessageBox.Show("Cliente possui limite de crédito de " + cli.limiteAtual.ToString("C") + "\n O Total dos cheques é de " + total.ToString("C"), "Erro!", MessageBoxButtons.OK);
                    }

                    else
                    {
                        foreach (Cheque c in lstCheques)
                        {
                            chequeDAO.cadastrarCheque(c);
                        }

                        double limite = cli.limiteAtual - total;

                        clienteDAO.atualizarLimiteCreditoCliente(limite, txtCpfCliente.Text);   

                        String trocostring = troco.ToString("C");

                        MessageBox.Show("Devolva ao cliente o valor de R$" + trocostring, "Cheques recebidos com sucesso!", MessageBoxButtons.OK);
                        
                        Utils.LimpaCampos(this);
                        txtDataSerasa.Text = DateTime.Now.ToString("dd/MM/yyyy");
                        
                        lstCheques = new List<Cheque>();
                        CarregarCheques();
                        CarregarClientes();
                    }
                }

                catch (Exception ex)
                {
                    MessageBox.Show("erro!");
                }
            }

            else
            {
                MessageBox.Show("É necessário validar os cheques antes de cadastra-los!");
            }
        }

        private void dataGridCliente_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                //verifico se o grid há linhas selecionadas
                if (dataGridCliente.CurrentRow != null)
                {
                    //capturo o codigo da grid
                    int cod = Convert.ToInt32(dataGridCliente.CurrentRow.Cells[0].Value);

                    //recupero o cliente que desejo alterar
                    var cliente = lstCliente.SingleOrDefault(x => x.id == cod);

                    //insiro seus valores nos controles
                    txtCpfCliente.Text = cliente.cpf;

                    lblLimit.Text = cliente.limiteAtual.ToString("C");
                    limiteClienteFactory = cliente.limiteAtual;

                    validou = false;
                }
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Erro!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnValidar_Click(object sender, EventArgs e)
        {
            //validando por risco de cpf
            validaListaDeChequesPorCPF();

            removerChequesNaoAprovadosPeloCpf();

            //validando por risco documento
            //validaListaDeChequesPorQtdDocumento();

            //removerChequesNaoAprovadosPorNumDocumento();

            validou = true;

            CarregarCheques();
        }

        private void label7_Click(object sender, EventArgs e)
        {

        }

        private void label8_Click(object sender, EventArgs e)
        {

        }

        private void btnRemover_Click(object sender, EventArgs e)
        {
            List<Cheque> cheq = lstCheques.Where(c => c.id == codChequeRemocao).ToList();
            lstCheques.Remove(cheq.FirstOrDefault());

            CarregarCheques();

           
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void btnLimpar_Click(object sender, EventArgs e)
        {
            Utils.LimpaCampos(this);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
            MenuPrincipal menuprincipal = new MenuPrincipal();
            menuprincipal.Show();
        }

        private void dataGridCheque_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void dataGridCheque_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                //verifico se o grid há linhas selecionadas
                if (dataGridCheque.CurrentRow != null)
                {
                    //capturo o codigo da grid
                    int cod = Convert.ToInt32(dataGridCheque.CurrentRow.Cells[0].Value);

                    //recupero o cliente que desejo alterar
                    var cheque = lstCheques.SingleOrDefault(x => x.id == cod);

                    //insiro seus valores nos controles
                    codChequeRemocao = cheque.id;

                    
                }
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Erro!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion
    }
}
